package com.panda.web.controller.order;

import com.panda.common.core.domain.R;
import com.panda.web.configuration.WxPayConfig;
import com.panda.web.domain.dto.OrderDTO;
import com.panda.web.entity.order.WechatOrder;
import com.panda.web.entity.product.OpenidProduct;
import com.panda.web.mapper.order.WechatOrderMapper;
import com.panda.web.mapper.product.OpenidProductMapper;
import com.panda.web.service.order.impl.WxRefundService;
import com.panda.web.utils.payutils.MiniWxPayUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.mybatis.logging.Logger;
import org.mybatis.logging.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.rmi.RemoteException;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@RestController
@RequestMapping("/api/refund")
public class RefundCallbackController {
    
    private static final Logger logger = LoggerFactory.getLogger(RefundCallbackController.class);
    @Autowired
    private WxRefundService refundOrder;
    @Autowired
    private WxPayConfig wxPayConfig;
    @Autowired
    private WechatOrderMapper orderMapper;
    @Autowired
    private OpenidProductMapper openidProductMapper;
    /**
     * 退款
     */
    @PostMapping("/wx/refund")
    public R wxRefund(@RequestBody OrderDTO dto) throws Exception {
        return R.ok(refundOrder.refund(dto));
    }
    /**
     * 微信退款回调通知
     * 注意：此接口需要返回明文XML响应
     */
    @PostMapping("/notify")
        public String refundNotify(@RequestBody String xmlData) {
        try {
            log.info("接收到退款通知: {}", xmlData);

            // 1. 解析XML
            Map<String, String> notifyMap = MiniWxPayUtil.xmlToMap(xmlData);
            log.info("XML解析成功: {}", notifyMap);

            // 3. 解密 req_info
            String encryptedInfo = notifyMap.get("req_info");
            log.info("待解密数据: {}", encryptedInfo);

            String decryptedInfo = decryptReqInfo(encryptedInfo);
            log.info("解密成功: {}", decryptedInfo);

            // 4. 解析解密后的XML
            Map<String, String> decryptedMap = MiniWxPayUtil.xmlToMap(decryptedInfo);
            log.info("解密数据解析成功: {}", decryptedMap);

            // 5. 获取退款信息
            String outRefundNo = decryptedMap.get("out_refund_no");
            String refundId = decryptedMap.get("refund_id");
            String outTradeNo = decryptedMap.get("out_trade_no");

            // 安全处理金额转换
            int refundFee = getIntValueSafely(decryptedMap, "refund_fee", "退款金额");
            int totalFee = getIntValueSafely(decryptedMap, "total_fee", "订单金额");
            String refundStatus = decryptedMap.get("refund_status");
            log.info("55555555555555555555555555555555");
            BigDecimal refundFeeA = new BigDecimal(refundFee).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
            log.info("666666666666666666666666666666666666");
            // 5. 处理退款记录
            WechatOrder order = orderMapper.findByOrderId(outTradeNo);
            if (order == null) {
                return errorResponse("退款记录不存在");
            }
            log.info("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
            // 6. 根据退款状态更新记录
            switch (refundStatus) {

                case "SUCCESS":
                    log.info("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
                    WechatOrder wechatOrder = orderMapper.findByOrderId(outTradeNo);
                    wechatOrder.setRefundId(refundId);
                    wechatOrder.setRefundOrderId(outRefundNo);
                    log.info(refundFeeA+"退款金额");
                    log.info(wechatOrder.getTotalFee()+"订单金额");
                    if (wechatOrder.getRefundFee().add(refundFeeA).compareTo(wechatOrder.getTotalFee())==0){
                        wechatOrder.setRefundStatus("全部退款"); //TODO  实现可部分退款
                        wechatOrder.setRefundFee(wechatOrder.getRefundFee().add(refundFeeA));

                        OpenidProduct openidProduct = openidProductMapper.findByProductIdAndOpenId(wechatOrder.getOpenid(), wechatOrder.getProductId());
                        if (openidProduct!=null){
                            openidProduct.setStatus("1");//停用
                            openidProductMapper.updateById(openidProduct);
                        }
                    }else if (wechatOrder.getRefundFee().add(refundFeeA).compareTo(wechatOrder.getTotalFee())<0){
                        wechatOrder.setRefundStatus("部分退款"); //实现可部分退款
                        wechatOrder.setRefundFee(wechatOrder.getRefundFee().add(refundFeeA));
                    }else if (wechatOrder.getRefundFee().add(refundFeeA).compareTo(wechatOrder.getTotalFee())>0){
                        throw new RemoteException("退款金额大于订单金额，无法退款");
                    }
                    Date date = new Date();
                    SimpleDateFormat simpleDateFormat =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    String format = simpleDateFormat.format(date);
                    wechatOrder.setRefundTime(format);
                    wechatOrder.setSuccessTime(format);

//                    wechatOrder.setUserReceivedAccount(userReceivedAccount);
                    orderMapper.updateById(wechatOrder);
                    break;

                case "CHANGE": // 退款异常
                    log.info("cccccccccccccccccccccccccccccccccccccccccc");
                    break;

                case "REFUNDCLOSE": // 退款关闭
                    log.info("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee");
                    break;

                default:
                    log.info("ffffffffffffffffffffffffffffffffffff");
                    return errorResponse("未知退款状态");
            }

            // 7. 返回成功响应
            return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";

        } catch (Exception e) {
            log.info("gggggggggggggggggggggggggggggggggggggg");
            return errorResponse("处理回调异常: " + e.getMessage());
        }
    }
    private int getIntValueSafely(Map<String, String> map, String key, String fieldName) {
        String value = map.get(key);
        try {
            return Integer.parseInt(value);
        } catch (NumberFormatException e) {
            throw new RuntimeException("无法解析" + fieldName + ": " + value);
        }
    }
    private String decryptReqInfo(String encryptedInfo) {
        try {
            // 1. Base64解码
            byte[] encryptedData = Base64.getDecoder().decode(encryptedInfo);

            // 2. 生成AES密钥（MD5(API_KEY)的小写HEX）
            String apiKey = wxPayConfig.getApiKey();
            byte[] apiKeyMd5 = MessageDigest.getInstance("MD5")
                    .digest(apiKey.getBytes(StandardCharsets.UTF_8));
            String md5KeyHex = bytesToHex(apiKeyMd5).toLowerCase(); // 转为小写HEX
            byte[] aesKey = md5KeyHex.getBytes(StandardCharsets.UTF_8);

            // 3. 检查数据长度是否为16的倍数
            if (encryptedData.length % 16 != 0) {
                log.error("加密数据长度无效: {}", encryptedData.length);
                throw new RuntimeException("数据长度不是AES块大小的倍数");
            }

            // 4. 使用AES-128-ECB解密
            SecretKeySpec secretKey = new SecretKeySpec(aesKey, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            byte[] decryptedBytes = cipher.doFinal(encryptedData);

            // 5. 返回UTF-8字符串
            return new String(decryptedBytes, StandardCharsets.UTF_8);
        } catch (Exception e) {
            log.error("解密失败: {}", encryptedInfo, e);
            throw new RuntimeException("解密失败: " + e.getMessage(), e);
        }
    }

    // 辅助方法：byte[]转HEX字符串
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }

    /**
     * 返回错误响应
     */
    private String errorResponse(String message) {
        return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[" + message + "]]></return_msg></xml>";
    }


}